
/*  exparg.c  source code for exparg()
 */

/******************************************************************************

  NAME    exparg - expand filespec command line parameters
         containing wild-card characters

  USAGE   #include "exparg.h"
      char **exparg (int *pargc, char *argv []);

  PROTOTYPE IN  exparg.h

  DESCRIPTION Exparg is used to explicitly process the filespec
      command line parameters containing wild-card
      characters. It takes a pointer to an integer
      containing the count of the parameters and a pointer
      to an array of pointers to the strings copied from
      the comamnd line. It is anticipated that most of the
      time exparg() will be called immediately upon entry
      to main(), with the call looking like

        argv = exparg (&argc, argv);

      See the test program included in this file for an
      example usage.

      When exparg() finds a filespec parameter string
      containing wild-card characters, it replaces the
      string with the name of the first file that matches
      it and adds the names of subsequent matches to the
      list of parameter string pointers. If no matching file
      names are found, the original string is left in place.

      Upon return from exparg() argc will be updated to
      indicate the new number of command line parameters
      and argv will point to a different array of string
      pointers. Command line parameter processing can then
      proceed as it would have been done before.

  RETURN VALUE  A pointer to an array of string pointers that point
      to the expanded filespec command line parameters. The
      int containing the parameter count is modified as a
      side-affect.

  PORTABILITY MS-DOS specific, Turbo-C specific

  AUTHOR    Richard Hargrove
      Texas Instruments, Inc.
      P.O. Box 869305, m/s 8473
      Plano, Texas 75086
      214/575-4128

 ******************************************************************************/

#include <stdio.h>
#include <string.h>
#include <dir.h>
#include <dos.h>
#include <alloc.h>
#include <process.h>

#define MAXARGS   100 /* maximum number of entries the new argv */
        /* array can contain        */

#define TRUE    1
#define FALSE   0
#define NIL(type) ((type *) NULL)

typedef int BOOLEAN;

/******************************************************************************/

char **exparg (int *pargc, char *argv [])
{
  static char *newargv [MAXARGS];
  char path [MAXPATH];    /* if the stack doesn't overflow, */
  char drive [MAXDRIVE];    /* we have less lasting impact    */
  char dir [MAXDIR];    /* on the static data segment     */

  char far *olddta = getdta ();
  struct ffblk fblk;
  register int args = 0;
  register int newargc = 0;
  BOOLEAN err = FALSE;

  while (!err && args < *pargc) {
    if ((fnsplit(argv[args],drive,dir,NIL(char),NIL(char))& WILDCARDS) &&
       (!findfirst (argv [args], &fblk, 0))) {
      do {
        char *localcptr = (char *)malloc (
    (unsigned)(stpcpy (stpcpy (stpcpy (path, drive),
             dir),
           fblk.ff_name) - path) + 1);
        if (localcptr != NIL(char)) {
    newargv [newargc++] = strcpy (localcptr, path);
        }
        else {
    fputs ("\n_exparg error : no memory for filenames\n", stderr);
    exit (1);
        }
      } while ((newargc < MAXARGS) && !findnext (&fblk));
    }
    else {
      newargv [newargc++] = argv [args];
    }
    err = (newargc == MAXARGS);
    args++;
  }

  if (err) fputs ("\n_exparg error : too many filenames\n", stderr);
  setdta (olddta);
  *pargc = newargc;
  return (&newargv [0]);
}

#ifdef TEST

/******************************************************************************/

main (int argc, char *argv [])
{
  /*  test exparg()
   */

  int i = 0;

  printf ("original command line parameters : argc: %d\n", argc);
  for (; i < argc; i++) {
    printf ("%s\n", argv [i]);
  }

  argv = exparg (&argc, argv);

  printf ("new command line parameters : argc: %d\n", argc);
  for (i = 0; i < argc; i++) {
    printf ("%s\n", argv [i]);
  }
}
#endif
